<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\ResourceAbstract;
use League\Fractal\Serializer\ArraySerializer;

class ApiController extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    protected $fractal;

    /**
     * @var int $statusCode
     */
    protected $statusCode = 200;

    /**
     * 返回的文字提示
     * @var string
     */
    protected $message = '';

    /**
     * @var int
     */
    protected $code = 0;

    /**
     * ApiController constructor.
     */
    public function __construct()
    {
        $this->fractal = new Manager();

        $this->fractal->setSerializer(new ArraySerializer());

        if ($include = app('request')->get('include')) {
            $this->fractal->parseIncludes($include);
        }
    }

    /**
     * @param $statusCode
     * @return $this
     */
    protected function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;

        return $this;
    }

    /**
     * @param $message
     * @return $this
     */
    protected function setMessage($message)
    {
        $this->message = $message;

        return $this;
    }

    /**
     * @param $code
     * @return $this
     */
    protected function setCode($code)
    {
        $this->code = $code;

        return $this;
    }

    /**
     * @param       $transformer
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function onlyTrans($transformer, array $headers = [])
    {
        $data = new Item([], $transformer);

        $data = $this->fractal->createData($data)->toArray();

        return $this->response($data, $headers);
    }

    /**
     * response a singular resource
     * @param                                              $item
     * @param \League\Fractal\TransformerAbstract|\Closure $transformer
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function item($item, $transformer, array $headers = [])
    {
        if (empty($item)) {
            return $this->hasNoData($headers);
        }

        return $this->hasData(new Item($item, $transformer), $headers);
    }

    /**
     * response the collection data.
     * @param \Illuminate\Support\Collection $collection
     * @param \League\Fractal\TransformerAbstract|\Closure $transformer
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function collection($collection, $transformer, array $headers = [])
    {
        if (!$collection->count()) {
            return $this->hasNoData($headers);
        }

        return $this->hasData(new Collection($collection, $transformer), $headers);
    }

    /**
     * 分页数据返回
     * @param \Illuminate\Pagination\LengthAwarePaginator $paginate
     * @param \League\Fractal\TransformerAbstract|\Closure $transformer
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function paginate($paginate, $transformer, array $headers = [], $count = 0)
    {
        if (!$paginate->count()) {
            return $this->hasNoData($headers);
        }

        $collection = $paginate->getCollection();

        $resource = new Collection($collection, $transformer);

        $resource->setPaginator(new IlluminatePaginatorAdapter($paginate));

        if ($count > 0) {
            $resource->setMetaValue('all_count',$count);
        }
        return $this->hasData($resource, $headers);
    }

    /**
     * 响应json数据
     * @param array|ResourceAbstract $array
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function response($array = [], array $headers = [])
    {
        if (empty($array)) {
            return $this->hasNoData($headers);
        }

        return $this->hasData($array, $headers);
    }

    /**
     * 没有查询到数据时的返回方法
     * @param string $message
     * @param string $code
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function hasNoData(array $headers = [], $message = '未查询到数据', $code = 40001)
    {
        return response()->json($this->format([], $message, $code), $this->statusCode, $headers);
    }

    /**
     * 查询到数据时的返回方法
     * @param        $array
     * @param string $message
     * @param string $code
     * @param array $headers
     * @return \Illuminate\Http\JsonResponse
     */
    protected function hasData($array, array $headers = [], $message = '执行成功', $code = 10000)
    {
        return response()->json($this->format($array, $message, $code), $this->statusCode, $headers);
    }

    /**
     * 固定返回结果的格式
     * @param        $array
     * @param string $message
     * @param string $code
     * @return array
     */
    protected function format($array, $message = '执行成功', $code = 10000)
    {
        $message = $this->message ?: $message;
        $code = $this->code ?: $code;

        if ($array instanceof ResourceAbstract) {
            $array = $this->fractal->createData($array)->toArray();
        }

        if ($array) {
            if (isset($array['data'])) {
                return array_merge($array, ['message' => $message, 'code' => $code]);
            }

            return ['data' => $array, 'message' => $message, 'code' => $code];
        } else {
            return ['message' => $message, 'code' => $code];
        }
    }

    /**
     * @param       $result
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     */
    protected function responseForUpdate($result, $data = [])
    {
        if (false === $result) {
            $this->message = '更新失败。稍后再试！';
            $this->code = 40002;
        } else {
            $this->message = '更新成功';
            $this->code = 10000;
        }

        return $this->response($data);
    }

    protected function responseForDelete($result, $message = null)
    {
        if ($result === false) {
            $this->message = $message ? $message : '删除失败。稍后再试！';
            $this->code = 40003;
        } else {
            $this->message = $message ? $message : '删除成功';
            $this->code = 10000;
        }

        return $this->response();
    }

    /**
     * json 控制器 验证响应
     * @param \Illuminate\Http\Request $request
     * @param array $errors
     * @return \Illuminate\Http\JsonResponse
     */
    protected function buildFailedValidationResponse(Request $request, array $errors)
    {
        return new JsonResponse($errors, 422);
    }

    /**
     * 数据返回处理
     *
     * @param int $errCode
     * @param string $errMsg
     * @param array $data
     * @param string $responseType
     */
    public function responseData($errCode, $errMsg, $data = [], $responseType = 'json') {
        $result = array(
            'code' => $errCode,
            'msg' => $errMsg
        );

        if(!empty($data)) {
            $result['data'] = $data;
        }

        //lvhq 180428 响应日志记录
        //log_message('response_content',json_encode($result));

        switch($responseType) {
            case 'json':
                echo json_encode($result);
                exit;
            case 'jsonp':
                $callback = $_REQUEST['callback'];
                echo $callback ."(". json_encode($result) .")";
                exit;
            default:
                echo json_encode($result);
                exit;
        }
    }
}